package com.example.gulimall.product.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.entity.order.OrderEntity;
import com.example.common.entity.product.SkuInfoEntity;
import com.example.common.entity.product.SpuInfoEntity;
import com.example.common.to.SkuReductionTo;
import com.example.common.to.kill.SecKillRedisTo;
import com.example.common.to.kill.SkuInfoTo;
import com.example.common.utils.PageUtils;
import com.example.common.utils.Query;
import com.example.common.utils.R;
import com.example.gulimall.product.dao.SkuInfoDao;
import com.example.gulimall.product.entity.SkuImagesEntity;
import com.example.gulimall.product.entity.SkuSaleAttrValueEntity;
import com.example.gulimall.product.feign.CouponFeignService;
import com.example.gulimall.product.feign.SecKillFeignService;
import com.example.gulimall.product.service.*;
import com.example.gulimall.product.vo.Attr;
import com.example.gulimall.product.vo.Images;
import com.example.gulimall.product.vo.Skus;
import com.example.gulimall.product.vo.item.SkuItemVo;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Slf4j
@Service("skuInfoService")
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfoEntity> implements SkuInfoService {


    @Autowired private MapperFacade mapperFacade;
    @Autowired private AttrGroupService attrGroupService;
    @Autowired private SkuImagesService skuImagesService;
    @Autowired private CouponFeignService couponFeignService;
    @Autowired private SpuInfoDescService spuInfoDescService;
    @Autowired private ThreadPoolExecutor threadPoolExecutor;
    @Autowired private SecKillFeignService secKillFeignService;
    @Autowired private SkuSaleAttrValueService attrValueService;
    @Autowired private SkuSaleAttrValueService skuSaleAttrValueService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {

        String key = (String) params.get("key");

        String catelogId = (String) params.get("catelogId");
        String brandId = (String) params.get("brandId");

        String min = (String) params.get("min");
        String max = (String) params.get("max");
        final String _default = "0";


        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                Wrappers.<SkuInfoEntity>lambdaQuery()
                        .like(StringUtils.isNotBlank(key), SkuInfoEntity::getSkuName, key)
                        .eq(StringUtils.isNotBlank(catelogId)
                                        && !_default.equalsIgnoreCase(catelogId),
                                SkuInfoEntity::getCatalogId, catelogId)
                        .eq(StringUtils.isNotBlank(brandId)
                                        && !_default.equalsIgnoreCase(brandId),
                                SkuInfoEntity::getBrandId, brandId)
                        .between(
                                StringUtils.isNotBlank(min)
                                        && !_default.equalsIgnoreCase(min)
                                        && StringUtils.isNotBlank(max)
                                        && !_default.equalsIgnoreCase(max),
                                SkuInfoEntity::getPrice,
                                min, max
                        )
        );

        return new PageUtils(page);
    }

    @Override
    public void saveSkuInfo(List<Skus> skus, SpuInfoEntity spuInfoEntity) {

        if (CollectionUtils.isEmpty(skus)) {
            return;
        }

        final int _default = 1;

        skus.forEach(
                a -> {

                    // 6.1 sku 基本信息 pms_sku_info
                    SkuInfoEntity infoEntity = new SkuInfoEntity();
                    BeanUtils.copyProperties(a, infoEntity);

                    infoEntity.setBrandId(spuInfoEntity.getBrandId())
                            .setCatalogId(spuInfoEntity.getCatalogId())
                            .setSaleCount(0L)
                            .setSpuId(spuInfoEntity.getId());


                    if (CollectionUtils.isNotEmpty(a.getImages())) {
                        for (Images image : a.getImages()) {
                            if (image.getDefaultImg() == _default) {
                                infoEntity.setSkuDefaultImg(image.getImgUrl());
                                break;
                            }
                        }
                    }
                    this.baseMapper.insert(infoEntity);

                    // 6.2 sku 图片信息 pms_sku_images
                    List<SkuImagesEntity> skuImages = a.getImages().stream().map(
                            b -> new SkuImagesEntity()
                                    .setImgUrl(b.getImgUrl())
                                    .setSkuId(infoEntity.getSkuId())
                                    .setDefaultImg(b.getDefaultImg())
                    )
                            .filter(img -> StringUtils.isNotBlank(img.getImgUrl()))
                            .collect(Collectors.toList());
                    this.skuImagesService.saveBatch(skuImages);


                    // 6.3 sku 销售属性 pms_sku_sale_attr_value
                    List<Attr> attr = a.getAttr();
                    if (CollectionUtils.isNotEmpty(attr)) {

                        List<SkuSaleAttrValueEntity> skuSaleAttrValueEntities = attr.stream().map(
                                c ->
                                        new SkuSaleAttrValueEntity()
                                                .setAttrId(c.getAttrId())
                                                .setAttrName(c.getAttrName())
                                                .setAttrValue(c.getAttrValue())
                                                .setSkuId(infoEntity.getSkuId())
                        ).collect(Collectors.toList());

                        this.attrValueService.saveBatch(skuSaleAttrValueEntities);
                    }

                    // 6.4 sku 优惠、满减信息   gulimall_sms -> sms_sku_ladder、sms_sku_full_reduction、sms_member_price
                    this.saveSkuReduction(a, infoEntity.getSkuId());
                }
        );
    }

    @Override
    public List<SkuInfoEntity> getSkusBySpuId(Long spuId) {
        return this.baseMapper.selectList(
                Wrappers.<SkuInfoEntity>lambdaQuery()
                .eq(SkuInfoEntity::getSpuId, spuId)
        );
    }

    private void saveSkuReduction(Skus skus, Long id) {
        SkuReductionTo reduction = new SkuReductionTo();
        BeanUtils.copyProperties(skus, reduction);
        reduction.setSkuId(id);

        if (reduction.getFullCount() > 0
                || reduction.getFullPrice().compareTo(BigDecimal.ZERO) > 0) {

            R r = this.couponFeignService.saveSkuReduction(reduction);

            if (r.getCode() != R.DEFAULT_CODE) {
                log.error("sku优惠信息调用失败： {}", r);
            }
        }
    }

    /**
     * 此方法被优化，使用异步方式进行同步查询
     *
     * @param skuId     商品销售信息ID
     */
    public SkuItemVo item(Long skuId) {
        SkuItemVo vo = new SkuItemVo();
        // 查询 sku 基本信息
        vo.setSkuInfoEntity(this.getById(skuId));
        // 查询 sku 图片信息
        vo.setImages(this.skuImagesService.getImagesBySkuId(skuId));
        // 查询 sku 销售属性
        vo.setSaleAttrs(this.skuSaleAttrValueService.getSaleAttrBySpuId(vo.getSkuInfoEntity().getSpuId()));
        // 查询 spu 介绍
        vo.setDesp(this.spuInfoDescService.getSpuInfoDesp(vo.getSkuInfoEntity().getSpuId()));
        // 查询 spu 规格与包装
        vo.setGroupAttrs(this.attrGroupService.getAttrGroupWithAttrsBySpuIdJoin(vo.getSkuInfoEntity().getSpuId(),
                vo.getSkuInfoEntity().getCatalogId()));
        return vo;
    }


    @Override
    @SneakyThrows
    public SkuItemVo itemPlus(Long skuId) {
        SkuItemVo vo = new SkuItemVo();

        // 查询 sku 基本信息
        CompletableFuture<SkuInfoEntity> skuInfoFuture = CompletableFuture.supplyAsync(
                () -> {
                    SkuInfoEntity info = this.getById(skuId);
                    vo.setSkuInfoEntity(info);
                    return info;
                }, this.threadPoolExecutor
        );
        // 查询 sku 销售属性
        CompletableFuture<Void> saleFuture = skuInfoFuture.thenAcceptAsync(
                res -> vo.setSaleAttrs(this.skuSaleAttrValueService.getSaleAttrBySpuId(res.getSpuId())),
                this.threadPoolExecutor
        );
        // 查询 spu 介绍
        CompletableFuture<Void> descFuture = skuInfoFuture.thenAcceptAsync(
                res -> vo.setDesp(this.spuInfoDescService.getSpuInfoDesp(res.getSpuId())),
                this.threadPoolExecutor
        );
        // 查询 spu 规格与包装
        CompletableFuture<Void> groupFuture = skuInfoFuture.thenAcceptAsync(
                res -> vo.setGroupAttrs(this.attrGroupService.getAttrGroupWithAttrsBySpuIdJoin(res.getSpuId(), res.getCatalogId())),
                this.threadPoolExecutor
        );
        // 查询 sku 图片信息
        CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(
                () -> vo.setImages(this.skuImagesService.getImagesBySkuId(skuId)), this.threadPoolExecutor
        );
        // 远程查询当前 sku 是否参与秒杀信息
        CompletableFuture<Void> killFuture = CompletableFuture.runAsync(
                () -> {
                    R info = this.secKillFeignService.getSkuInfo(skuId);
                    if (info.getCode() == R.DEFAULT_CODE) {
                        vo.setSecKill(info.getData(new TypeReference<SecKillRedisTo>() {
                        }));
                    }
                }, this.threadPoolExecutor
        );

        /* 等待所有任务完成 */
        CompletableFuture.allOf(skuInfoFuture, saleFuture, descFuture, groupFuture, imageFuture, killFuture).get();
        return vo;
    }

    @Override
    public List<SkuInfoEntity> getNewPrice(List<Long> skuId) {

        if (CollectionUtil.isEmpty(skuId)) {
            return Collections.emptyList();
        }

        List<SkuInfoEntity> entities = this.baseMapper.selectBatchIds(skuId);
        if (CollectionUtil.isEmpty(entities)) {
            return Collections.emptyList();
        }
        return entities;
    }

    @Override
    public List<SkuInfoTo> getSkuInfo(List<Long> skuIds) {

        List<SkuInfoEntity> entities = this.baseMapper.selectList(
                Wrappers.<SkuInfoEntity>lambdaQuery()
                        .in(SkuInfoEntity::getSkuId, skuIds)
        );

        return this.mapperFacade.mapAsList(entities, SkuInfoTo.class);
    }


}